//
// Created by denglibin on 2019/6/17 0017.
//

/**
 *lambda表达式语法定义:
 *  [capture] （parameters） mutable ->return-type {statement};
 （1） [capture]: 捕捉列表。捕捉列表总是出现在lambda函数的开始处。实质上，[]是lambda引出符（即独特的标志符）

　　编译器根据该引出符判断接下来的代码是否是lambda函数

　　捕捉列表能够捕捉上下文中的变量以供lambda函数使用

　　捕捉列表由一个或多个捕捉项组成，并以逗号分隔，捕捉列表一般有以下几种形式：
    <1> [var] 表示值传递方式捕捉变量var

　　<2> [=] 表示值传递方式捕捉所有父作用域的变量（包括this指针）

　　<3> [&var] 表示引用传递捕捉变量var

　　<4> [&] 表示引用传递捕捉所有父作用域的变量（包括this指针）

　　<5> [this] 表示值传递方式捕捉当前的this指针

　　<6> [=，&a，&b] 表示以引用传递的方式捕捉变量 a 和 b，而以值传递方式捕捉其他所有的变量

　　<7> [&，a，this] 表示以值传递的方式捕捉 a 和 this，而以引用传递方式捕捉其他所有变量
备注:父作用域是指包含lambda函数的语句块

 另外，需要注意的是，捕捉列表不允许变量重复传递。下面的例子就是典型的重复，会导致编译错误：

　　[=， a] 这里 = 已经以值传递方式捕捉了所有的变量，那么再捕捉 a 属于重复

　　[&，&this] 这里 & 已经以引用传递方式捕捉了所有变量，那么再捕捉 this 属于重复

 （2）（parameters）:参数列表。与普通函数的参数列表一致。如果不需要参数传递，则可以连同括号（）一起省略

 （3）mutable : mutable修饰符。默认情况下，lambda函数总是一个const函数，mutable可以取消其常量性（后面有详解）

　　在使用该修饰符时，参数列表不可省略（即使参数为空

（4）->return-type : 返回类型。用追踪返回类型形式声明函数的返回类型。

　　出于方便，不需要返回值的时候也可以连同符号->一起省略

 此外，在返回类型明确的情况下，也可以省略该部分，让编译器对返回类型进行推导

 （5）{statement} : 函数体。内容与普通函数一样，不过除了可以使用参数之外，还可以使用所有捕获的变量

　　在lambda函数的定义中，参数列表和返回类型都是可选的部分，而捕捉列表和函数体都可能为空

　　那么，在极端情况下，C++11中最为简单的lambda函数只需要声明为：

　　[] {};

　　就可以了。不过显然，这样的lambda函数不能做任何事情（乍一看好漂亮，其实只是好看）。
 * */

#include <iostream>
using namespace std;

int main50(){
    int a = 20, b = 10;
    auto sum = [](int x, int y)->int{return x + y;};
    cout << sum(a, b) << endl;

    auto sum2 = [a, &b]()->int{ return a + b; };
    cout << sum2() << endl;

    auto sum3 = [=]()->int{return a + b;};
    cout << sum2() << endl;

    []{cout << "nothing" << endl;}; // 最简lambda函数
    cout << [=] { return a + b; }() << endl; // 省略了参数列表与返回类型，返回类型由编译器推断为int ():表示调用

    auto fun1 = [&] (int c) { b = a + c; }; // 省略了返回类型，无返回值
    fun1(2);
    cout << b << endl; //22

    auto fun2 = [=, &b](int c)->int { return b += a + c; }; // 各部分都很完整的lambda函数
    fun2(3);
    cout << b << endl; // 22+20+3 = 45
    return 0;
}